<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>3D trees</title>

<link rel="stylesheet" href="https://js.arcgis.com/4.0/esri/css/main.css">
<script src="https://js.arcgis.com/4.0/"></script>

<style>
html,
body,
#viewDiv {
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
}
</style>

<script>
require([
    "esri/Map",
    "esri/views/SceneView",
    "esri/layers/FeatureLayer",
    "esri/geometry/SpatialReference",
    "esri/geometry/Point",
    "esri/Camera",
    "esri/PopupTemplate",
    "esri/renderers/SimpleRenderer",
    "esri/symbols/PointSymbol3D",
    "esri/symbols/ObjectSymbol3DLayer",
    "dojo/domReady!"
  ],
  function(
    Map, SceneView, FeatureLayer, SpatialReference, Point, Camera, PopupTemplate, SimpleRenderer, PointSymbol3D, ObjectSymbol3DLayer
  ) {

    var initCam = {
      position: {
        x: -9178258,
        y: 4247301,
        z: 930,
        spatialReference: { wkid: 3857 }
      },
      heading: 89,
      tilt: 70
    };

    /*****************************************************************
     * Renderer and Layer for the tree trunks. Since visual variables only
     * work for one symbol layer in version 4.0 of the ArcGIS JS API,
     * we need to separate the trunks from the crowns in different layers.
     *
     * This is subject to change in future releases of the API
     *****************************************************************/

    var trunkRenderer = new SimpleRenderer({
      symbol: new PointSymbol3D({
        symbolLayers: [new ObjectSymbol3DLayer({
          material: { color: "brown" },
          resource: { primitive: "cylinder" }
        })]
      }),
      visualVariables: [
        {
          type: "size",
          axis: "height",
          field: "Height",
          valueUnit: "feet"
        }, {
          type: "size",
          axis: "width-and-depth",
          field: "DBH1",
          valueUnit: "inches"
        }
      ]
    });

    var trunkLyr = new FeatureLayer({
       url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0",
       renderer: trunkRenderer,
       outFields: ["*"],
       elevationInfo: {
         mode: "on-the-ground"
       },
       definitionExpression: "Height >= 14 AND Height <= 40"
    });

    /*****************************************************************
     * Renderer and Layer for the tree crowns. Four visual variables
     * are used in this symbol. One for the crown height (height axis),
     * another for crown diameter from north to south (depth axis), and
     * another for crown diameter from east to west (width axis).
     *
     * The color visual variable shades the tree crowns based on their
     * Carbon storage.
     *****************************************************************/

    var crownRenderer = new SimpleRenderer({
       symbol: new PointSymbol3D({
         symbolLayers: [new ObjectSymbol3DLayer({
           material: { color: "green" },
           resource: { primitive: "sphere" }
         })]
       }),
       visualVariables: [
         {
          type: "size",
          axis: "height", // set the crown height on the height axis
          field: "Crown_Height", // Crown heights are expressed in feet
          valueUnit: "feet" // converts and extrudes all data values in feet
        }, {
          type: "size",
          axis: "width", // set the crown diameter (east to west) to the width axis
          field: "Width_EW", // crown diameter (EW) is expressed in feet
          valueUnit: "feet" // converts and extrudes all data values in feet
        }, {
          type: "size",
          axis: "depth", // set the crown diameter (north to south) to the depth axis
          field: "Width_NS", // crown diameter (NS) is expressed in feet
          valueUnit: "feet" // converts and extrudes all data values in feet
        }, {
          type: "color",
          field: "C_Storage",  // Carbon storage
          stops: [
            { value: 0, color: "#f7fcb9" },
            { value: 800, color: "#31a354" }
          ]
        }
       ]
    });

    var crownLyr = new FeatureLayer({
       url: "http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0",
       renderer: crownRenderer,
       outFields: ["*"],
       elevationInfo: {
         mode: "relative-to-ground",
         offset: 6.5
       },
       definitionExpression: "Height >= 14 AND Height <= 40",
       popupTemplate: {
         title: "{Cmn_Name}",
         content: "<i>{Sci_Name}</i><br>" +
           "This tree is in {Condition} condition and is {Height} feet in height."
       }
     });

    /*****************************************************************
     * Add the layer to a map
     *****************************************************************/
    var map = new Map({
      basemap: "osm",
      ground: "world-elevation",
      layers: [ trunkLyr, crownLyr ]
    });

    var view = new SceneView({
      container: "viewDiv",
      map: map,
      camera: initCam
    });
  });
</script>
</head>

<body>
  <div id="viewDiv"></div>
</body>

</html>